\chapter{PCRE2常用接口与选项}\label{pcre2-app-interface}

\section{正则表达式编译}
为加速正则匹配，在使用正则表达式匹配之前，需要对正则表达式进行编译，PCRE2实现
正则表达式编译的接口为：

\begin{minipage}{0.90\textwidth}
  \begin{ccode}
    pcre2_code *pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE length,
                              uint32_t options,
                              int *errorcode, PCRE2_SIZE *erroroffset,
                              pcre2_compile_context *ccontext);
  \end{ccode}
\end{minipage}

参数含义：
\begin{description}
  \item[\cinline{pattern}:] 需要编译的正则表达式
  \item[\cinline{length}:] 正则表达式长度或\cinline{PCRE2_ZERO_TERMINATED}
  \item[\cinline{options}:] 选项(用不同位的开关表示设置与否)
  \item[\cinline{errorcode}:] 错误编码
  \item[\cinline{erroffset}:] 错误信息偏移量
  \item[\cinline{ccontext}:] 编译上下文指针或\cinline{NULL}
\end{description}

其中，\cinline{length}和\cinline{erroffset}的长度单位为编码单位%
(\cinline{PCRE2_CODE_UNIT_WIDTH}宏指定的单位)而不是字符单位，编译上下文仅在需要
提供指定的内存分配函数，或指定外部系统栈尺寸检查，或如下情况时使用：
\begin{itemize}
  \item 指定\cinline{'\R'}的匹配内容(UNICODE newlinw或仅CR、LF、CRLF)
  \item PCRE2的字符表
  \item newline字符序列
  \item 编译时有嵌套括号限制
  \item 允许的最大模式(正则表达式)长度(编码单位)
  \item 附加的选项位
\end{itemize}

\cinline{options}选项有：
\begin{description}
  \item[\cinline{PCRE2_ANCHORED}:] 强制模式(正则表达式)中的锚定
  \item[\cinline{PCRE2_ALLOW_EMPTY_CLASS}:] 允许\cinline{[]}空列表
  \item[\cinline{PCRE2_ALT_BSUX}:] 允许\cinline{'\u'}，\cinline{'\U'}和\cinline{'\x'}运算符
  \item[\cinline{PCRE2_ALT_CIRCUMFLEX}:] 允许允许在多行模式下使用\cinline{'^'}运算符
  \item[\cinline{PCRE2_ALT_VERBNAMES}:] 允许动词中的\verb|'\'|
  \item[\cinline{PCRE2_AUTO_CALLOUT}:] 编译自动回调函数
  \item[\cinline{PCRE2_CASELESS}:] 不区分大小写
  \item[\cinline{PCRE2_DOLLAR_ENDONLY}:] \cinline{'$'}符不匹配尾部的newline
  \item[\cinline{PCRE2_DOTALL}:] \cinline{'.'}符可以匹配包括NL的任意字符
  \item[\cinline{PCRE2_DUPNAMES}:] 允许在子模式中出现重复名称
  \item[\cinline{PCRE2_ENDANCHORED}:] 仅在尾部进行匹配
  \item[\cinline{PCRE2_EXTENDED}:] 忽略空白和\cinline{'#'}注释
  \item[\cinline{PCRE2_FIRSTLINE}:] 强制在newline之前进行匹配
  \item[\cinline{PCRE2_LITERAL}:] 模式(正则表达式)字符均为字面字符
  \item[\cinline{PCRE2_MATCH_INVALID_UTF}:] 启用匹配无效UTF支持
  \item[\cinline{PCRE2_MATCH_UNSET_BACKREF}:] 匹配未设置的反向引用
  \item[\cinline{PCRE2_MULTILINE}:] \cinline{'^'}和\cinline{'$'}匹配newlines
  \item[\cinline{PCRE2_NEVER_BACKSLASH_C}:] 禁止在模式(正则表达式)中使用\cinline{'\C'}
  \item[\cinline{PCRE2_NEVER_UCP}:] 禁用\cinline{PCRE2_UCP}，例如\cinline{(*UCP)}
  \item[\cinline{PCRE2_NEVER_UTF}:] 禁用\cinline{PCRE2_UTF}，例如\cinline{(*UTF)}
  \item[\cinline{PCRE2_NO_AUTO_CAPTURE}:] 禁用编号分组(可使用命名分组)
  \item[\cinline{PCRE2_NO_AUTO_POSSESS}:] 禁用自动处理
  \item[\cinline{PCRE2_NO_DOTSTAR_ANCHOR}:] 禁用\cinline{.*}的自动锚定
  \item[\cinline{PCRE2_NO_START_OPTIMIZE}:] 禁用匹配时间启动优化
  \item[\cinline{PCRE2_NO_UTF_CHECK}:] 不检查模式(正则表达式)的UTF有效性
  \item[\cinline{PCRE2_UCP}:] 为\cinline{'\d'}、\cinline{'\W'}等运算符启用UNICODE属性
  \item[\cinline{PCRE2_UNGREEDY}:] 反转量词的贪婪匹配
  \item[\cinline{PCRE2_USE_OFFSET_LIMIT}:] 启用非锚定匹配的偏移限制
  \item[\cinline{PCRE2_UTF}:] 将模式(正则表达式)和匹配对象视为UTF字符串
\end{description}

该函数返回指向正则缓存(编译后的正则表达式，一种内部数据结构)的指针，
如果编译失败则返回\cinline{NULL}。

\section{匹配寄存器}

匹配寄存器是用于保存匹配结果的一种数据结构，它用一个数组逐个记录匹配及其分组
匹配的起始和终止位置。每一个成功的匹配占两个元素，构成一个匹配向量。

可以通过编译后的正则表达式得到创建匹配寄存器，其函数原型为：

\begin{minipage}{0.90\textwidth}
  \begin{ccode}
    pcre2_match_data *pcre2_match_data_create_from_pattern(
              const pcre2_code *code, pcre2_general_context *gcontext);
  \end{ccode}
\end{minipage}

其中，\cinline{code}用于指定正则缓存(编译后的正则表达式)，模式中的括号分组数量确定
了匹配向量对数。\cinline{gcontext}用于指和向用于自定义内存管理的上下文，如果是系统
内部进行内存管理，则取\cinline{NULL}。

该函数返回匹配寄存器的指针。
%
% 也可以通过指定匹配寄存器的大小来创建匹配寄存器，其函数原型为：
%
% \begin{minipage}{0.90\textwidth}
%   \begin{ccode}
%     pcre2_match_data *pcre2_match_data_create(uint32_t ovecsize,
%                                         pcre2_general_context *gcontext);
%   \end{ccode}
% \end{minipage}
%
% 其中，\cinline{ovecsize}用于指定匹配对数(正则表达式的分组)，若取0则表示只有
% 一个分组。\cinline{gcontext}用于指和向用于自定义内存管理的上下文，如果是系统
% 内部进行内存管理，则取\cinline{NULL}。
%
% 该函数返回匹配寄存器的指针。

\section{正则匹配}

在完成正则表达式的编译及创建了用于记录匹配结果的匹配寄存器后，就可以进行正则
匹配了，其函数原型为：

\begin{minipage}{0.90\textwidth}
  \begin{ccode}
    int pcre2_match(const pcre2_code *code,
                    PCRE2_SPTR subject,
                    PCRE2_SIZE length,
                    PCRE2_SIZE startoffset,
                    uint32_t options,
                    pcre2_match_data *match_data,
                    pcre2_match_context *mcontext);
  \end{ccode}
\end{minipage}

该函数与Perl的匹配算法类似，用编译后的正则表达式(\cinline{code})与给定的
字符串(\cinline{subject})进行匹配。并将匹配结果的起始与结束偏移量(编码单位
表示的字符位置)写入 \cinline{match_data} 指定的匹配寄存器中。其参数含义如下：

\begin{description}
  \item[\cinline{code}:] 正则缓存(编译后的正则表达式)指针
  \item[\cinline{subject}:] 待匹配字符串
  \item[\cinline{length}:] 待匹配字符串长度或\cinline{PCRE2_ZERO_TERMINATED}
  \item[\cinline{startoffset}:] 匹配起始位置
  \item[\cinline{options}:] 选项(用不同位的开关表示设置与否)
  \item[\cinline{match_data}:] 匹配寄存器指针
  \item[\cinline{mcontext}:] 匹配上下文指针或\cinline{NULL}
\end{description}

一般在如下情况下使用匹配上下文：

\begin{itemize}
  \item 设置回调函数
  \item 设置匹配偏移限制
  \item 更改堆内存限制
  \item 更改回溯匹配限制
  \item 更改回溯深度限制
  \item 为匹配指定专用内存管理方法
\end{itemize}

\cinline{options}选项有：

\begin{description}
  \item[\cinline{PCRE2_ANCHORED}:] 仅匹配第一个位置
  \item[\cinline{PCRE2_COPY_MATCHED_SUBJECT}:] 成功时，生成匹配对象的私有拷贝
  \item[\cinline{PCRE2_ENDANCHORED}:] 仅在末尾进行匹配
  \item[\cinline{PCRE2_NOTBOL}:] 待匹配字符串不在行开始
  \item[\cinline{PCRE2_NOTEOL}:] 待匹配字符串不在行末尾
  \item[\cinline{PCRE2_NOTEMPTY}:] 空串匹配是无效匹配
  \item[\cinline{PCRE2_NOTEMPTY_ATSTART}:] 在待匹配字符串开始的空串匹配是无效匹配
  \item[\cinline{PCRE2_NO_JIT}:] 禁用JIT匹配
  \item[\cinline{PCRE2_NO_UTF_CHECK}:] 不检查待匹配字符串的UTF有效性%
      (仅在设置\cinline{PCRE2_UTF}编译选项时适用)
  \item[\cinline{PCRE2_PARTIAL_HARD}:] 如果存在部分匹配，也返回 %
      \cinline{PCRE2_ERROR_PARTIAL} 以表示部分匹配，即使存在完全匹配
  \item[\cinline{PCRE2_PARTIAL_SOFT}:] 如果存在部分匹配，则返回 %
      \cinline{PCRE2_ERROR_PARTIAL} 以表示部分匹配，即使不存在完全匹配
\end{description}

该函数返回比设置的最高捕获对多1的正数(例如，如果没有捕获，则返回1)，如果设置的
偏移量太小，则返回0,如果没有匹配或发生其它错误，则返回负数表示的错误代码。
%
% \begin{minipage}{0.90\textwidth}
%   \begin{ccode}
%     int pcre2_dfa_match(const pcre2_code *code,
%                         PCRE2_SPTR subject,
%                         PCRE2_SIZE length,
%                         PCRE2_SIZE startoffset,
%                         uint32_t options,
%                         pcre2_match_data *match_data,
%                         pcre2_match_context *mcontext,
%                         int *workspace,
%                         PCRE2_SIZE wscount);
%   \end{ccode}
% \end{minipage}

\section{内存释放}

在完成正则匹配后，结束程序前，需要将正则缓存(编译后的正则表达式)和匹配寄存器占有的内存
进行释放。

释放正则缓存的函数原型为：

\begin{minipage}{0.90\textwidth}
  \begin{ccode}
    void pcre2_code_free(pcre2_code *code);
  \end{ccode}
\end{minipage}

释放匹配寄存器的函数原型为：

\begin{minipage}{0.90\textwidth}
  \begin{ccode}
    void pcre2_match_data_free(pcre2_match_data *match_data);
  \end{ccode}
\end{minipage}
